package net.imagine.backend.mockrmi.remote.provider.netty.client;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import net.imagine.backend.mockrmi.util.Constants;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;

/**
 * Netty框架实现的客户端管理类
 * 
 * @author wuqh
 * @see ClientBootstrap
 * @see Channel
 */
public class NettyClientContext {
	private static final Log logger = LogFactory.getLog(NettyClientContext.class);
	private final ClientBootstrap bootstrap;

	public NettyClientContext() {
		bootstrap = createBootstrap();
	}

	/**
	 * 创建ClientBootstrap
	 * 
	 * @return 创建的ClientBootstrap
	 */
	private ClientBootstrap createBootstrap() {
		ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(
				Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));

		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(
						new ObjectEncoder(Constants.OBJECT_ESTIMATE_LEN),
						new ObjectDecoder(Constants.OBJECT_MAX_LEN, ClassResolvers.weakCachingResolver(this.getClass()
								.getClassLoader())), new NettyClientIoHandler());
			}
		});

		bootstrap.setOption("receiveBufferSize", Constants.CLIENT_RECEIVE_BUFFER_SIZE);
		bootstrap.setOption("sendBufferSize", Constants.CLIENT_SEND_BUFFER_SIZE);
		bootstrap.setOption("keepAlive", Constants.CLIENT_KEEP_ALIVE);
		bootstrap.setOption("connectTimeoutMillis", Constants.CLIENT_CONN_TIMEOUT_MILLIS);
		return bootstrap;
	}

	/**
	 * 创建Channel
	 * 
	 * @param domain
	 *            服务端地址
	 * @param port
	 *            服务器端口号
	 * @return 创建的Channel
	 */
	public Channel createChannel(String domain, int port) {
		try {
			ChannelFuture future = bootstrap.connect(new InetSocketAddress(domain, port));
			future.awaitUninterruptibly();
			Channel channel = future.getChannel();
			channel.setReadable(true);
			return channel;
		} catch (Exception e) {
			logger.warn("create session failed", e);
			return null;
		}
	}

	/**
	 * 关闭Channel（需要等待IO完成）
	 * 
	 * @param channel
	 *            需要关闭的channel
	 */
	public void releaseChannel(Channel channel) {
		channel.close();
	}

	/**
	 * 关闭管理的ClientBootstrap，结束线程（需要等待IO完成）
	 * 
	 */
	public void releaseBootstrap() {
		bootstrap.releaseExternalResources();
	}
}
